'''
$LastChangedBy: csgillespie $
$LastChangedDate: 2007-06-06 11:08:06 +0000 (Wed, 06 Jun 2007) $
Darren Wilkinson and Colin Gillespie (c.gillespie@ncl.ac.uk)

Used to generate a tree for the compartments.
Using CompartmentTree we can calculate the dependencies of
each compartment
'''

class CompartmentTree:
	'''Used to generate a tree for the compartments.
	Using CompartmentTree we can calculate the dependencies of
	each compartment
	'''
	def __init__(self):
		self.children = []
		self.node = {}
		
	def add(self, comp):
		'''Adds a compartment to the tree
	
		If the outside variable of the tree has not been declared
		then the it also adds the outside compartment to the tree
		'''
	
		#Checks to see if the compartment is already in the tree
		if comp.name not in self.node:
			self.node[comp.name] = comp
		elif comp.outside:
			self.node[comp.name].outside = comp.outside
			
		#Checks if the compartment has outside and whether outside is
		#is in the tree	
		if comp.outside and comp.outside not in self.node:
			self.node[comp.outside] = CompartmentNode(comp.outside)
		
		#Arranges the tree
		if comp.outside:
			self.node[comp.outside].children.append(self.node[comp.name])
		else:
			self.children.append(self.node[comp.name])
	
	def string(self):
		'''Prints out the sbml of the compartments'''
		
		sbml_cp = '<listOfCompartments>\n'
		for child in self.children:
			sbml_cp = sbml_cp + child.string()
		sbml_cp = sbml_cp + '</listOfCompartments>'
		return sbml_cp
	
	def delCompartment(self, cp_id):
		'''Given a compartment, a list is return with all the dependencies.'''
		
		list_of_ids = []
		for child in self.children:
			list_of_ids = child.findEnd(cp_id, list_of_ids)
		return list_of_ids
			
class CompartmentNode:
	'''Used in CompartmentTree'''
	
	def __init__(self, name, outside=None):
		self.name = name
		self.outside = outside
		self.children = []

	def __str__(self):
		return str(self.name)

	def string(self):
		'''Prints out a snippet of SBML'''
		sbml_cp = '<compartment name="' + str(self) + '"'
		if (self.outside):
			sbml_cp = sbml_cp + ' outside="' + self.outside + '"'
		sbml_cp = sbml_cp+'/>\n'
		for child in self.children:
			sbml_cp = sbml_cp+child.string()
		return sbml_cp

	def findEnd(self, cp_id, list_of_ids=None):
		'''Given a compartment id, it will return all its children'''
		if list_of_ids is None:
			list_of_ids = []
		if self.name in cp_id and self.name not in list_of_ids:
			list_of_ids.append(self.name)
			self.constructList(list_of_ids)
		for child in self.children:
			list_of_ids = child.findEnd(cp_id, list_of_ids)
		return list_of_ids
		
	def constructList(self, list_of_ids):
		'''TODO'''
		for child in self.children:
			list_of_ids.append(child.name)
			child.constructList(list_of_ids)
		return list_of_ids
